package znet

import (
	"errors"
	"fmt"
	"io"
	"net"

	"github.com/desyang-hub/zinx_demo/utils"
	"github.com/desyang-hub/zinx_demo/zface"
)

type Connection struct {
	Conn     *net.TCPConn
	ConnID   uint32
	isClose  bool
	ExitChan chan bool
	MsgChan  chan []byte // 用于Reader和Writer两个goroutine之间的通信

	MsgHandler zface.IMsgHandler
}

func (c *Connection) StartClientReader() {
	// 退出后 Stop
	defer c.Stop()

	var mid uint32 = 0

	// 从客户端中读数据
	for {
		// 拆包和解包
		dp := NewDataPack()

		buf := make([]byte, dp.GetHeadLen())
		n, err := io.ReadFull(c.Conn, buf)

		if err != nil && err != io.EOF {
			// 异常
			fmt.Println("read head err: ", err)
			break
		}

		if n == 0 {
			break
		}

		var msg zface.IMessage
		msg, err = dp.UnPack(buf)

		if err != nil {
			fmt.Println("unpack err: ", err)
			break
		}

		if msg.GetMsgLen() > utils.AppContext.MaxPackagesSize {
			fmt.Println("package len excced MaxPackagesSize")
			break
		}

		// 继续读取data
		buf = make([]byte, msg.GetMsgLen())
		if _, err := io.ReadFull(c.Conn, buf); err != nil {
			fmt.Println("Read data err: ", err)
			break
		}

		msg.SetMsgData(buf)

		request := NewRequst(c, msg)

		c.MsgHandler.SendRequestToMaskQueue(mid, request)
		mid += 1

		// 使用IMsgHandler来处理Request
		// go c.MsgHandler.DoMsgHandler(request)
	}
}

func (c *Connection) StartClientWriter() {

	defer fmt.Println(c.Conn.RemoteAddr().String() + "[Conn Writer exists!]")

	for {
		select {
		case data := <-c.MsgChan:
			if _, err := c.Conn.Write(data); err != nil {
				fmt.Println("Send Message to client err: ", err)
				return
			}
		case <-c.ExitChan:
			// Reader 发现客户端已经退出
			return
		}
	}
}

func (c *Connection) Start() {
	go c.StartClientReader()
	go c.StartClientWriter()
}

func (c *Connection) Stop() {
	if c.isClose {
		return
	}

	c.isClose = true
	c.ExitChan <- true
	// 关闭
	c.Conn.Close()

	close(c.ExitChan)
	close(c.MsgChan)
}

func (c *Connection) GetTCPConn() *net.TCPConn {
	return c.Conn
}

func (c *Connection) GetConnID() uint32 {
	return c.ConnID
}

func (c *Connection) GetRemoteAddr() net.Addr {
	return c.Conn.RemoteAddr()
}

func (c *Connection) Send(msgID uint32, data string) error {
	dp := NewDataPack()
	msg := &Message{
		MsgID:   msgID,
		MsgLen:  uint32(len(data)),
		MsgData: []byte(data),
	}

	buf, err := dp.Pack(msg)

	if err != nil {
		return errors.New("data pack err " + err.Error())
	}

	// if _, err := c.Conn.Write(buf); err != nil {
	// 	return errors.New("server write err: " + err.Error())
	// }

	// 将需要发送的信息写入到MsgChan中
	c.MsgChan <- buf

	return nil
}

func NewConnection(conn *net.TCPConn, connId uint32, msgHandler zface.IMsgHandler) zface.IConnection {
	return &Connection{
		Conn:       conn,
		ConnID:     connId,
		isClose:    false,
		MsgHandler: msgHandler,
		ExitChan:   make(chan bool),
		MsgChan:    make(chan []byte),
	}
}
